package com.kk.xhr.web.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Optional;

/**
 * Jwt工具类
 *
 * @author kkmystery
 * @version 1.0 2021/3/9
 * @since 1.0.0
 */
public class JwtUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtUtil.class);
    private static final String CLAIM_NAME = "userId";
    public static final String TOKEN_NAME = "Authorization";
    private static final String secret = "xhr-backend";
    private static final Long expired = 604800L;

    private JwtUtil() {
    }

    /**
     * 校验JWT字符串
     *
     * @param token jwt token
     * @param claim 用户标识(username)
     * @return 是否通过
     */
    public static boolean verify(String token, String claim) {
        try {
            Algorithm algorithm = Algorithm.HMAC512(secret);
            JWTVerifier verifier = JWT.require(algorithm).withClaim(CLAIM_NAME, claim).build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            LOGGER.debug("Verify jwt token {} failed.", token);
        }
        return false;
    }

    /**
     * 获取jwt关键信息，不用解码
     *
     * @param token jwt token
     * @return claim 用户标识
     */
    public static Optional<String> getClaim(String token) {
        try {
            return Optional.of(JWT.decode(token).getClaim(CLAIM_NAME).asString());
        } catch (JWTDecodeException e) {
            LOGGER.warn("Can't decode jwt {}", token);
        }
        return Optional.empty();
    }

    /**
     * 签名jwt token串
     *
     * @param claim 用户标识
     * @return token
     */
    public static String sign(String claim) {
        Algorithm algorithm = Algorithm.HMAC512(secret);
        Date expiredDate = new Date(System.currentTimeMillis() + expired);
        return JWT.create().withClaim(CLAIM_NAME, claim).withExpiresAt(expiredDate).sign(algorithm);
    }

    /**
     * 刷新令牌
     *
     * @param token 原令牌
     * @return 新令牌
     */
    public static String refreshToken(String token) {
        String refreshedToken;
        try {
            String claim = getClaim(token).get();
            return sign(claim);
        } catch (Exception e) {
            refreshedToken = null;
        }
        return refreshedToken;
    }
}
